package com.informix.stream.api.records;

import com.informix.stream.api.IfmxStreamOperationRecord;
import com.informix.stream.common.enums.IfmxStreamRecordType;

import java.nio.ByteBuffer;
import java.sql.Connection;
import java.util.*;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class IfxCDCOperationRecord extends IfxCDCRecord implements IfmxStreamOperationRecord {
    private final Logger logger = LoggerFactory.getLogger(IfxCDCOperationRecord.class);
    private final byte[] buffer;
    private final LinkedHashMap<String, LinkedHashMap<String, String>> columns;
    private final Connection con;
    private final LinkedHashMap<String, Object> objects = new LinkedHashMap();

    public IfxCDCOperationRecord(
            IfmxStreamRecordType type,
            byte[] header,
            byte[] buffer,
            Map<String, LinkedHashMap<String, LinkedHashMap<String, String>>> columns,
            Connection con
    ) {
        super(type);
        this.buffer = buffer;
        this.con = con;
        ByteBuffer headerBuffer = ByteBuffer.wrap(header);
        this.sequence = headerBuffer.getLong();
        this.transaction = headerBuffer.getInt();
        this.label = Integer.toString(headerBuffer.getInt());
        this.columns = columns.get(this.label);
        this.logger.debug("New IfxCDCOperationRecord created. Label: {}", this.label);
    }

    @Override
    public synchronized Map<String, Object> getData() {
        ByteBuffer buffer = ByteBuffer.wrap(this.buffer);
        if (!this.objects.isEmpty()) {
            return this.objects;
        } else {
            int offset = 0;
            for (String columnName : this.columns.keySet()) {
                Map<String, String> columnInfo = this.columns.get(columnName);
                String colType = columnInfo.get("colType");
                if ((colType.equals("bigint"))) {
                    this.objects.put(columnName, buffer.getLong());
                } else if ((colType.equals("varchar"))) {
                    int VARCHAR_DES_LEN = 2;
                    byte[] varDesLen = new byte[VARCHAR_DES_LEN]; // 根据数据库版本定义varchar字段长度描述符长度，默认为2，低版本为1
                    buffer.get(varDesLen);
                    int length = 0;
                    if (VARCHAR_DES_LEN == 2) {
                        length = (int) varDesLen[0] & 0xFF << 8 | varDesLen[1] & 0xFF;
                    } else {
                        length = (int) varDesLen[0];
                    }
                    byte[] b = new byte[length];
                    buffer.get(b);
                    this.objects.put(columnName, length == 1 && b[0] == '\0' ? null : new String(b));
                }
            }
        }
        return this.objects;

    }

    @Override
    public boolean hasOperationData() {
        return true;
    }
}
